package com.example.test_2_1_transaction.controller;


import com.example.test_2_1_transaction.service.LogService;
import com.example.test_2_1_transaction.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RequestMapping("/proge")
@RestController
public class ProController {
    /**
     *演示事务的传播机制
     */
    @Autowired
    private UserService userService; // service 里面也带有 事务注解
    @Autowired
    private LogService logService;// service 里面也带有 事务注解

    /**
     * 正常操作, 没有抛出异常
     */
    @Transactional // 此时什么都不写 就是默认值 REQUIRED, 调用的事务 如果成功 整体都成功了

    // 那如果吧 日志表中的service 层 弄成失败的会怎么样?
    // 默认值情况下, 运行之后的结果会报异常
    // 运行结果是 事务没有提交, 用户表和日志表都没有提交
    // 也就是 如果其中一个失败那么整体就都失败了, UserService 用的都是默认的

    // 这时候把 UserService 和 LogService 都改成 REQUIRES_NEW 的事务传播机制
    // 此时运行之后, inset 完之后 控制台还是报错了
    // 但, userService 的 运行结果成功了, 事务提交了
    // LogService 的运行结果失败了, 事务没有提交
    // , 但是这两个事务之间互不影响

    // 当把 UserService 和 LogService 改成嵌套事务传播机制的话
    //          |-------> insertUser (NESTED)
    //    p1 ---                            //还是这样一个关系
    //          |-------> insertLog  (NESTED)

    // 运行结果演示, 运行成功, 并且两个表的事务都提交成功了
    // 这样的展示, 就是 各自事务全部运行成功时, 结果都成功, 结果都成功了
    //      但是 其中有一个事务报错的话, 运行结果: 控制台出现遗产
    //      整个将全部失败, 都没有提交成功

    // 这样的结果 和 默认的 REQUIRED 情况一样
    // 那么 REQUIRED 和 NESTED 有什么区别呢?
    // NESTED 嵌套机制的话, 如果其中有一个子事务出现了问题
    // 可以让这个子事务自行去抛异常 自行去回滚, 这样就不会影响到父事务了

    // 这样运行结果, user_info 表就不会收到影响了
    // 只有 log_info 自行回滚了 (此处定义LogService包异常)
    // 但是如果是 REQUIRED 机制的话, 即使再自行回滚, 也都会进行全部回滚

    @RequestMapping("/p1")
    public String p1(String userName,String password){
        Integer result= userService.insertUser(userName, password);
        log.info("用户插入成功, result:"+result);

        Integer result2 = logService.insertLog(userName, "用户自行注册");
        log.info("日志表插入成功, result:"+result2);
        return "注册成功";
    }

}
